using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;


namespace PicAFlick.Domain
{
    public class VirtualImage : IDisposable
    {

        private Image _realImage;

        public Image RealImage
        {
            get { return _realImage; }
        }
        private Image _currentImageView;


        public Image CurrentImageView
        {
            get
            {
         
                

                return _currentImageView;
            }
        }

        public VirtualImage(Image sourceImage)
        {
            _realImage = sourceImage;
        }


        public void Dispose()
        {
            if (this._realImage != null)
            {
                _realImage.Dispose();
            }
            if (this._currentImageView != null)
            {
                _currentImageView.Dispose();

            }
        }


        private decimal _zoomLevel = 1;

        public decimal ZoomLevel
        {
            get {
                if (_zoomLevel <= 0)
                {
                    _zoomLevel = 1;
                }
                return _zoomLevel;
            }
            set 
            { 
                _zoomLevel = value;
               // _viewportTopLeft.X = 
                FireUpdateImage();
            }
        }

        private Size _viewportWindow = new Size(1, 1);


        public Size ViewportWindow
        {
            get { return _viewportWindow; }
            set 
            { 
                _viewportWindow = value;
                FireUpdateImage();
            }
        }

        private Point _viewportTopLeft = new Point(0,0);

        public Point ViewportTopLeft
        {
            get { return new Point((int)(_viewportTopLeft.X ), (int)(_viewportTopLeft.Y )); }
            set {
                _viewportTopLeft.X = (int)(value.X);
                _viewportTopLeft.Y = (int) (value.Y);
                FireUpdateImage();
            }
        }

        public Point ViewPortCentre
        {
            set
            {
                if (value.X < 0)
                {
                    value.X = 0;
                }
                if (value.Y < 0)
                {
                    value.Y = 0;
                }
                
                
                _viewportTopLeft.X = Math.Max(0, (int)( value.X - (int)(0.5 * ViewportWindow.Width)));
                _viewportTopLeft.Y = Math.Max(0, (int)(value.Y  - (int)(0.5 * ViewportWindow.Height)));
                FireUpdateImage();
            }
        }

        public int HorizontalMaxViewportTopLeft
        {
            get
            {
                return Math.Max((int)(_realImage.Width * _zoomLevel - _viewportWindow.Width),0);
            }
        }

        public int HorizontalMinViewportTopLeft
        {
            get
            {
                return 0;
            }
        }


        public int VerticalMinViewportTopLeft
        {
            get
            {
                return 0;
            }
        }

        public int VerticalMaxTopLeft
        {
            get
            {
                return Math.Max((int)(_realImage.Height * _zoomLevel - _viewportWindow.Height), 0);
            }

        }

        public decimal VerticalCurrentTopLeft
        {
            get
            {
                return Math.Min(_viewportTopLeft.Y, VerticalMaxTopLeft);
            }
        }
        public decimal HorizontalCurrentTopLeft
        {
            get
            {
                return Math.Min(_viewportTopLeft.X , HorizontalMaxViewportTopLeft);
            }
        }


        public delegate void ViewPortImageUpdatedHandler(object sender, EventArgs e);
        public event ViewPortImageUpdatedHandler OnViewportImageUpdated;



        public void ActualSize()
        {
            //actual size means 1 pixel = 1 pixel which occurs are zoom level = 1
            this._zoomLevel = 1;
            FireUpdateImage();
        }

        private void FireUpdateImage()
        {
            //calculate what our current viewport sees

            Image I = new Bitmap(_viewportWindow.Width, _viewportWindow.Height);

            int x = (int)((double)_viewportTopLeft.X );
            int y = (int)((double)_viewportTopLeft.Y );
            float xDist = (float)_viewportWindow.Width / (float)ZoomLevel;
            float yDist = (float)_viewportWindow.Height / (float)ZoomLevel;
            Graphics g = Graphics.FromImage(I);
            g.DrawImage(_realImage, new Rectangle(0, 0, I.Width, I.Height), new Rectangle(x, y, (int)xDist, (int)yDist), GraphicsUnit.Pixel);
            _currentImageView = I;
   






            if (OnViewportImageUpdated != null)
            {
                OnViewportImageUpdated(this, new EventArgs());
            }
        }

        public void FitToViewport()
        {
            //fit to view means choosing a zoom that will fit the image inside the current viewport

            decimal HorizontalZoom = (decimal)ViewportWindow.Width / _realImage.Width;
            decimal VerticalZoom = (decimal)ViewportWindow.Height / _realImage.Height;

            decimal FitToZoom = HorizontalZoom;
            if (FitToZoom > VerticalZoom)
            {
                FitToZoom = VerticalZoom;
            }

            _zoomLevel = FitToZoom;
            _viewportTopLeft = new Point(0,0);
            FireUpdateImage();
        }
        

    }
}
